﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;
using System.IO;
using System.Data.SqlClient;
using MySql.Data.MySqlClient;
namespace ChatServer
{
    class ChatServer
    {
        private IPAddress _ipAddress;
        private TcpClient _tcpClient;
        private Thread _listenerThread;
        private TcpListener _tcpListener;
        private List<string> _callsigns = new List<string>();
        public static Hashtable Users = new Hashtable();
        public static Hashtable Connections = new Hashtable();

        public ChatServer(IPAddress ip)
        {
            this._ipAddress = ip;
        }
        public void StartListening()
        {
            _tcpListener = new TcpListener(Properties.Settings.Default.ChatServerPort);
            _tcpListener.Start();
            _listenerThread = new Thread(Listening);
            _listenerThread.Start();
        }
        private void Listening()
        {
            StreamReader sr;
            StreamWriter sw;
            string response;
            while (true)
            {
                _tcpClient = _tcpListener.AcceptTcpClient();
                sr = new StreamReader(_tcpClient.GetStream());
                sw = new StreamWriter(_tcpClient.GetStream());
                string callsign = sr.ReadLine();
                Users.Add(_tcpClient, callsign);
                Connections.Add(callsign, _tcpClient);
                _callsigns.Add(callsign);
                SendMessage("", "@CONSOLE " + callsign + " has entered");
                Thread t = new Thread(()=>ClientListener(_tcpClient));
                t.Start();
            }
        }
        public void ClientListener(TcpClient client)
        {
            string callsign = Convert.ToString(Users[client]);
            string message;
            StreamReader sr = new StreamReader(client.GetStream());
            try
            {
                while ((message = sr.ReadLine()) != "")
                {
                    SendMessage(callsign, message);
                }
            }
            catch (IOException e)
            {
                //Client closed connection
                Connections.Remove(callsign);
                Users.Remove(client);
                _callsigns.Remove(callsign);
                SendMessage("", "@CONSOLE " + callsign + " has left");
            }
        }
        public void SendMessage(string callsign, string message)
        {
            
             SendMessageToAll(callsign,message);
             using (MySqlConnection con = new MySqlConnection(Properties.Settings.Default.SDTConnectionString))
             {
                 con.Open();
                 string sql= "Insert into ChatRecord (Callsign, Time, Message) values (@callSign, @time, @message) ";
                 using (MySqlCommand command = new MySqlCommand(sql, con))
                 {
                     try
                     {
                         command.Parameters.AddWithValue("@callSign",callsign);
                         command.Parameters.AddWithValue("@time",DateTime.Now);
                         command.Parameters.Add("@message",message);
                         command.ExecuteNonQuery();
                     }
                     catch (Exception e)
                     {

                     }
                 }

             }
        }
        private void SendMessageToAll(string callsign, string message)
        {

            TcpClient[] clients = new TcpClient[Connections.Count];
            Connections.Values.CopyTo(clients, 0);
            StreamWriter sw;
            foreach (TcpClient client in clients)
            {
                sw = new StreamWriter(client.GetStream());
                sw.WriteLine(callsign + ":  " + message);
                sw.Flush();
                sw = null;
            }
        }
        public void SendDirectMessage(string callsign, string message)
        {
            string addressedUser = "";
            TcpClient client;
            StreamWriter sw;
            int index=0;
            try{

                index =message.IndexOf(' ');
                addressedUser = message.Substring(1,index).Trim();
            }
            catch (Exception e) 
            {
                index = 0;
            }
            //make sure message exist
            if (index < message.Length)
            {
                if (addressedUser == "CONSOLE")
                {

                    message = message.Substring(index);
                    SendMessageToAll("CONSOLE", message);
                }
                else
                {
                    if (_callsigns.Contains(addressedUser) && Connections.ContainsKey(addressedUser) && (client = Connections[addressedUser] as TcpClient) != null)
                    {
                        string messageText = callsign + ":  " + message; 
                        //send message to sender 
                        TcpClient sender = Connections[callsign] as TcpClient;
                        sw = new StreamWriter(sender.GetStream());
                        sw.WriteLine(messageText);
                        sw.Flush();

                        //send to receiver
                        sw = new StreamWriter(client.GetStream());
                        sw.WriteLine(messageText);
                        sw.Flush();
                        sw = null;
                    }
                    else
                    {
                        client = Connections[callsign] as TcpClient;
                        sw = new StreamWriter(client.GetStream());
                        sw.WriteLine("The addressed user is currently unavailable ");
                        sw.Flush();
                    }
                }
            }
        }

    }
}
